package cn.wangkai.peanut.action.filter;

import java.io.IOException;
import java.util.Enumeration;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang.BooleanUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import cn.wangkai.peanut.cache.WebCacheManager;
import cn.wangkai.peanut.util.RequestContext;


public class ControllerFilter implements Filter {
	private final static Log log = LogFactory.getLog(ControllerFilter.class);
	protected String encoding;
	protected boolean badkeyfilter;
	protected String errpage;
	protected String badStr;
	protected FilterConfig filterConfig;
	protected boolean ignore;
	protected String[] badStrs;
	private ServletContext context;  
	private RequestContext rc;
	private boolean cachemode;
	
	public ControllerFilter() {
		encoding = null;
		filterConfig = null;
		ignore = true;
	}

	/**
	 * 过滤器初始化
	 */
	public void init(FilterConfig filterConfig) throws ServletException {
		this.context = filterConfig.getServletContext();
		this.filterConfig = filterConfig;
		if(filterConfig.getInitParameter("ignore")==null)
			ignore = true;
		else
			ignore = BooleanUtils.toBoolean(filterConfig.getInitParameter("ignore"));
		encoding = filterConfig.getInitParameter("encoding");
		
		//是否需要字符过滤
		if(filterConfig.getInitParameter("badkeyfilter")==null)
			badkeyfilter = true;
		else{
			badkeyfilter = BooleanUtils.toBoolean(filterConfig.getInitParameter("badkeyfilter"));
		}
		if(badkeyfilter){
			errpage = filterConfig.getInitParameter("errpage");
			badStr = filterConfig.getInitParameter("badstr");
	        if(errpage==null) errpage = "/WEB-INF/jsp/errpage/keywordfail.jsp";
	        //过滤掉的sql关键字，可以手动添加
	        if(StringUtils.isEmpty(badStr)) badStr="'|exec|insert|select|delete|update|count|chr|mid|master|truncate|declare|<script>";
	        try{
	        	badStrs = badStr.split("\\|"); 
	        }catch (Exception e) {
			}
		}
		//是否开启缓冲
		if(filterConfig.getInitParameter("cachemode")==null)
			cachemode = false;
		else{
			cachemode = BooleanUtils.toBoolean(filterConfig.getInitParameter("cachemode"));
		}
		log.debug("检测系统是否开启缓冲!");
		if(cachemode){
			WebCacheManager.cachemode = true;
			log.debug("系统开启缓冲!");
			WebCacheManager.start();
		}
	}

	/**
	 * 执行过滤操作
	 */
	public void doFilter(ServletRequest req, ServletResponse res,
			FilterChain chain) throws IOException, ServletException {
		HttpServletRequest request = (HttpServletRequest) req;
		HttpServletResponse response = (HttpServletResponse) res;
		String url = request.getRequestURI();
		rc = RequestContext.begin(this.context, request, response);  
		if (ignore || request.getCharacterEncoding() == null) {
			String encoding = selectEncoding(request);
			if (encoding != null) {
				request.setCharacterEncoding(encoding);
			}
		}
		if(url.indexOf(".xwy")>=0||url.indexOf(".jsp")>=0) closeCache(response);

		if (url.indexOf("/.svn/") >= 0) {
			log.error(".svn path");
			error(response,HttpServletResponse.SC_FORBIDDEN,null);
			return;
		}
		if(badkeyfilter){
			//获得所有请求参数名  
			@SuppressWarnings("rawtypes")
			Enumeration params = req.getParameterNames();
			String sql = "";
			while (params.hasMoreElements()) {
				//得到参数名  
				String name = params.nextElement().toString();  
				String[] value = req.getParameterValues(name);  
	
				for (int i = 0; i < value.length; i++) {  
					sql = sql + value[i];  
				}
			}
			if (sqlValidate(sql)) {  
				request.getRequestDispatcher(errpage).forward(request, response);//跳转到信息提示页面！！   
				return;
			}
		}
		chain.doFilter(req, res);
	}

	/**
	 * 过滤器释放资源
	 */
	public void destroy() {
		encoding = null;
		filterConfig = null;
		if(rc!=null)
		rc.end();
		if(cachemode){
			log.debug("关闭缓冲");
			WebCacheManager.stop();
		}
	}

    protected boolean sqlValidate(String str) {
    	if(badStrs==null||!badkeyfilter) return true;
    	if(StringUtils.isEmpty(str)) return false;
        str = str.toLowerCase();//统一转为小写  
        for (int i = 0; i < badStrs.length; i++) {  
            if (str.indexOf(badStrs[i]) >= 0) {  
                return true;  
            }  
        }  
        return false;  
    }
	
	protected String selectEncoding(ServletRequest request) {
		return encoding;
	}

	/**
	 * 显示错误
	 * 
	 * @param response
	 * @param code
	 * @param msg
	 * @throws IOException
	 */
	public void error(HttpServletResponse response, int code, String[] msg)
			throws IOException {
		if (msg.length > 0)
			response.sendError(code, msg[0]);
		else
			response.sendError(code);
	}

	public void closeCache(HttpServletResponse response) {
		response.setHeader("Pragma", "No-cache");
		response.setHeader("Cache-Control", "no-cache");
		response.setDateHeader("Expires", 0);
	}
}
